package com.example.trackcircuitdiagnosis.time;

import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.example.trackcircuitdiagnosis.config.MqttProviderConfig;
import com.example.trackcircuitdiagnosis.dto.KGLresDTO;
import com.example.trackcircuitdiagnosis.dto.KGLretryDTO;
import com.example.trackcircuitdiagnosis.entity.DeviceInformationEntity;
import com.example.trackcircuitdiagnosis.service.DeviceInformationService;
import com.example.trackcircuitdiagnosis.utils.RedisUtils;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.fasterxml.jackson.databind.node.ObjectNode;
 import javax.annotation.PostConstruct;
 import javax.annotation.Resource;

import com.google.common.collect.Range;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.annotation.Order;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import com.fasterxml.jackson.core.type.TypeReference;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

/**
 * 定时发送数据组件
 * 用于定时将模拟量和开关量数据发送至MQTT消息队列
 */
@Component
@Order(2)
public class SendData {
    @Resource
    private RedisUtils redisUtils;

    // 用于JSON处理的ObjectMapper
    public ObjectMapper objectMapper = new ObjectMapper();

    @Autowired
    private MqttProviderConfig providerClient;

    // 用于计数秒数
    private int secondCount = 1;

    @Autowired
    private MyScheduledTask myScheduledTask;

    // 模拟量数据主题
    private final String analogDataZpw2000aTopic = "/analogData";
    private final String analogData25HZTopic = "/25HzanalogData";

    private final String currentTime = "/currentTime";

    // 获取当前环境配置
    @Value("${spring.profiles.active}")
    private String environment;

    @Value("${track.resource.data}")
    private String dataZpw2000aPath;

    @Value("${track.resource.25hzdata}")
    private String data25HzPath;



//    private String dataZpw2000aPath;
//
//    private String data25HzPath;
//    @PostConstruct
//    private void init(){
//        dataZpw2000aPath= Objects.equals(environment, "dev")?"D:\\sb\\data\\":"/home/java/data/";
//        data25HzPath= Objects.equals(environment, "dev")?"D:\\sb\\25Hzdata\\":"/home/java/25Hzdata/";
//    }
    /**
     * 使用 @Scheduled注解绑定执行的任务，参数以cron表达式设定执行时间及频率
     * 每秒钟执行一次，用于定时将模拟量和开关量数据发送至MQTT消息队列
     *
     * @throws JsonProcessingException JSON处理异常
     *
     *
     */
    @Scheduled(fixedRate = 250)
    public void send() throws JsonProcessingException {

        // 判断任务是否在运行
//
        if (StringUtils.equals(environment, "dev")) {
            return;
        }
        if (myScheduledTask.isTaskRunning()) {
            secondCount = myScheduledTask.sendTime;
            myScheduledTask.setTaskRunning(false);
        }

        sendRangeMessageAsync();

        String dataZpw2000a=readTxtAnalogData(dataZpw2000aPath);
        String data25Hz=readTxtAnalogData(data25HzPath);
//             发送模拟量数据至MQTT
        sendMqtt(analogDataZpw2000aTopic, dataZpw2000a,true);
        sendMqtt(analogData25HZTopic, data25Hz, true);
        sendMqtt(currentTime, String.valueOf(secondCount),false);

        secondCount++;

        // 重置秒数计数
        if (secondCount > 86400) {
            secondCount = 1;
        }
    }
    ExecutorService executorService = Executors.newSingleThreadExecutor();



    public void sendRangeMessageAsync(){
        executorService.submit(new Runnable() {
            @Override
            public void run() {
                Map<Range<Integer>, String> rangeMessageMap = new HashMap<>();
                rangeMessageMap.put(Range.closed(12342, 13062), "模拟网络盘配线端子混");
                rangeMessageMap.put(Range.closed(24684, 25404), "发送端电缆接地");
//                rangeMessageMap.put(Range.closed(52968, 53688), "断轨");
//                rangeMessageMap.put(Range.closed(39726, 40446), "接收室外端匹配变压器故障");
                rangeMessageMap.put(Range.closed(66210, 66930), "模拟网络盘配线假焊");
//                rangeMessageMap.put(Range.closed(79452, 80172), "室内送端软线开路");
//                rangeMessageMap.put(Range.closed(86300, 86400), "分线盘至电缆盒的电缆不良");
                try {
                    for (Map.Entry<Range<Integer>, String> entry : rangeMessageMap.entrySet()) {
                        if (entry.getKey().contains(secondCount)) {
                            sendMqtt("/status", entry.getValue(), false);
                            return;
                        }
                    }
                    sendMqtt("/status", "一切正常", false);
                } catch (JsonProcessingException e) {
                    e.printStackTrace();
                }


            }
        });
    }
    /**
     * 从Redis获取模拟量数据并转换为JSON格式
     *
     * @return 模拟量数据的JSON字符串
     * @throws JsonProcessingException JSON处理异常
     */
    public String readRedisAnalogData() throws JsonProcessingException {
        String key = String.valueOf(secondCount % 86400);
        if (!redisUtils.hasKey(key)) {
            return "未能加载数据";
        }
        List<Object> object = redisUtils.lGet(key, 0, -1);
        List<Double> floats = convertObjectsToFloats(object);
        return objectMapper.writeValueAsString(floats);
    }

    /**
     * 将Object类型列表转换为Double类型列表
     *
     * @param objects Object类型列表
     * @return Double类型列表
     */
    public List<Double> convertObjectsToFloats(List<Object> objects) {
        return objects.stream()
                .map(object -> (Double) object)
                .collect(Collectors.toList());
    }

    /**
     * 发送开关量数据至MQTT
     *
     * @return 开关量数据的JSON字符串
     * @throws JsonProcessingException JSON处理异常
     */
    public String readRedisKGL() throws JsonProcessingException {
        Object kgl = redisUtils.lGetIndex("kgl", secondCount - 1);
        KGLretryDTO kgLretries = (KGLretryDTO) kgl;

        return objectMapper.writeValueAsString(kgLretries);
    }

    /**
     * 发送MQTT消息
     *
     * @param topic   消息主题
     * @param message 消息内容
     */
    public void sendMqtt(String topic, String message,boolean isData) throws JsonProcessingException {
        providerClient.publish(2, false, topic, message,isData);
    }


    /**
     * 读取文本文件内容
     *
     * @param filePath 文件路径
     * @return 文件内容字符串
     */
    private String readTxtFile(String filePath) {
        StringBuilder content = new StringBuilder();
        try (BufferedReader reader = new BufferedReader(new FileReader(filePath))) {
            reader.lines().forEach(content::append);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return content.toString();
    }

    private String readTxtAnalogData(String  dataPath) {
        return readTxtFile(dataPath + secondCount + ".txt");
    }


}
